#include <stdio.h>
#include <stdlib.h>
#include "MOD2.h"


ListPtr ReadyQueue;
//ListPtr WaitQueue;
ListPtr BlockQueue;
ListPtr SusReadyQueue;
ListPtr SusBlockQueue;

/*/ Beginning of functions*/
void queue_init(void){
ReadyQueue = malloc(sizeof(List));
ReadyQueue->head=NULL;
ReadyQueue->tail=NULL;
//WaitQueue =  malloc(sizeof(List));
//WaitQueue->head=NULL;
//WaitQueue->tail=NULL;
BlockQueue = malloc(sizeof(List));
BlockQueue->head=NULL;
BlockQueue->tail=NULL;
SusReadyQueue = malloc(sizeof(List));
SusReadyQueue->head=NULL;
SusReadyQueue->tail=NULL;
SusBlockQueue = malloc(sizeof(List));
SusBlockQueue->head=NULL;
SusBlockQueue->tail=NULL;

}

void insertpcb(char *data, char *queue){

	if(!strcmp(queue,"ready")){
	   insert(ReadyQueue, data);
	}
	else if(!strcmp(queue, "blocked")){
	      insertfifo(BlockQueue, data);
	}
	else if(!strcmp(queue, "suspended-ready")){
	      insertfifo(SusReadyQueue, data);
	}
	else if(!strcmp(queue, "suspended-blocked")){
	      insertfifo(SusBlockQueue, data);
	}
	else{
	   printf("Invalid process state!\n");
	   return;
	}
}
void removepcb(char *data, char *queue){
	if(!strcmp(queue,"ready")){
	   if(!isEmpty(ReadyQueue)){
	      if(delete(ReadyQueue, data)){
		 printf("%s deleted.\n", data);
		 }
	      else
		 printf("%s not found.\n", data);
	      }
	      else if(isEmpty(ReadyQueue)){
		 printf("List is empty.\n");
		 return;
	      }
	}

	else if(!strcmp(queue, "blocked")){
	   if(!isEmpty(BlockQueue)){
	      if(delete(BlockQueue, data)){
		 printf("%s deleted.\n", data);
		 }
	      else
		 printf("%s not found.\n", data);
	      }
	      else if(isEmpty(BlockQueue)){
		 printf("List is empty.\n");
		 return;
	      }
	}
	else if(!strcmp(queue, "suspended-ready")){
	   if(!isEmpty(SusReadyQueue)){
	      if(delete(SusReadyQueue, data)){
		 printf("%s deleted.\n", data);
		 }
	      else
		 printf("%s not found.\n", data);
	      }
	      else if(isEmpty(SusReadyQueue)){
		 printf("List is empty.\n");
		 return;
	      }
	}
	else if(!strcmp(queue, "suspended-blocked")){
	   if(!isEmpty(SusBlockQueue)){
	      if(delete(SusBlockQueue, data)){
		 printf("%s deleted.\n", data);
		 }
	      else
		 printf("%s not found.\n", data);
	      }
	      else if(isEmpty(SusBlockQueue)){
		 printf("List is empty.\n");
		 return;
	      }
	}
	else{
	   printf("Invalid process state!\n");
	   return;
	}
}
void show (char *option){

	if(!strcmp(option, "all")){
	   printf("The following strings are contained in system queues:\n");
	   printf("*****************************************************\n");
	   printf("Ready:\n");
	   printList("ready");
	   printf("\n");
	   printf("Waiting:\n");
	   printList("waiting");
	   printf("\n");
	   printf("Blocked:\n");
	   printList("blocked");
	   printf("\n");
	   printf("Suspended-Ready:\n");
	   printList("suspended-ready");
	   printf("\n");
	   printf("Suspended-Blocked:\n");
	   printList("suspended-blocked");
	}
	else{
	   printf("The following strings are contained in the %s queue:\n",  option);
	   printf("****************************************************\n");
	   printList(option);
	}
}


void insert(ListPtr sPtr, char *value)
{
	ListNodePtr newPtr;
	ListNodePtr prevPtr;
	ListNodePtr currPtr;

	newPtr = malloc(sizeof(ListNode));
	newPtr->nextPtr=NULL;
	newPtr->data = malloc(strlen(value)+1 * sizeof(char));

	strcpy(newPtr->data, value);

	if(newPtr !=NULL){

		prevPtr = NULL;
		currPtr = sPtr->head;

		if (currPtr == NULL) {
			sPtr->head = newPtr;
			return;
		}
		while(currPtr != NULL && strcmp(value, currPtr -> data) > 0 )
		{
			prevPtr = currPtr;
			currPtr = currPtr ->nextPtr;
		}

		if(prevPtr == NULL)
		{
			newPtr -> nextPtr = sPtr->head;
			sPtr->head = newPtr;
		}
		else if( prevPtr != NULL && currPtr != NULL)
		{
			prevPtr -> nextPtr = newPtr;
			newPtr -> nextPtr = currPtr;
		}
		else if(prevPtr != NULL && currPtr == NULL)
		{
		   prevPtr->nextPtr = newPtr;
		}
	}
	else
	{
		printf("Not inserted. No memory avaliable.\n");
	}
}

void insertfifo(ListPtr sPtr, char *value){
	ListNodePtr newPtr;
	//ListNodePtr head = NULL;
	//ListNodePtr tail = NULL;
	ListNodePtr prevPtr;
	ListNodePtr currPtr;

	newPtr = malloc(sizeof(ListNode));
	newPtr->nextPtr=NULL;
	newPtr->data=malloc(strlen(value)+1 * sizeof(char));

	strcpy(newPtr->data, value);

	if(newPtr != NULL){
		prevPtr=NULL;
		currPtr=sPtr->tail;

		if(isEmpty(sPtr)){
            printf("empty\n");
			sPtr->head=newPtr;
			sPtr->tail=newPtr;
		}
		else{
			prevPtr=currPtr;
			currPtr=currPtr->nextPtr;
			prevPtr->nextPtr=newPtr;
			sPtr->tail=newPtr;
		}
	}
	else{
		printf("%s is not inserted. No memory available.\n", value);
	}
}

char delete(ListPtr sPtr, char *value)
{
	ListNodePtr tempPtr=NULL;
	ListNodePtr prevPtr=NULL;
	ListNodePtr currPtr;

	if(strcmp(value, sPtr -> head ->data) == 0)
	{

		tempPtr =sPtr->head;
		sPtr->head = sPtr->head->nextPtr;
		free(tempPtr->data);
		free(tempPtr);
		return 1;
	}
	else
	{
		prevPtr = sPtr->head;
		currPtr = prevPtr->nextPtr;

		while(currPtr != NULL && strcmp(currPtr -> data, value) !=0)
		{
			prevPtr = currPtr;
			currPtr = currPtr ->nextPtr;
		}

		if(currPtr != NULL)
		{
			tempPtr = currPtr;
			prevPtr -> nextPtr = currPtr -> nextPtr;
			free(tempPtr->data);
			free(tempPtr);
			return 1;
		}
	}
	return 0;
}

int isEmpty(ListPtr sPtr)
{
	if(sPtr->head == NULL)
	return (1);
	else
	return (0);
}

void printList(char *queueName)
{
	ListNodePtr next;
	ListPtr currPtr;

	if(strcmp(queueName, "ready") ==0){ currPtr = ReadyQueue;

	if(currPtr->head == NULL)
	{

		printf("List is empty.\n");
	}
	else
	{
		next = currPtr->head;
		while(next != NULL)
		{
			printf("%s  ", next->data);
			next = next->nextPtr;
		}
		printf("\n");
	}
	}

	else if(strcmp(queueName, "blocked") ==0){ currPtr = BlockQueue;

	if(currPtr->head == NULL)
	{
		printf("List is empty.\n");
	}
	else
	{
		next = currPtr->head;
		while(next != NULL)
		{
			printf("%s  ", next -> data);
			next = next->nextPtr;
		}
		printf("\n");
	}
	}
	else if(strcmp(queueName, "suspended-ready") ==0){ currPtr = SusReadyQueue;

	if(currPtr->head == NULL)
	{
		printf("List is empty.\n");
	}
	else
	{
		next = currPtr->head;
		while(next != NULL)
		{
			printf("%s  ", next -> data);
			next = next->nextPtr;
		}
		printf("\n");
	}
	}
	else if(strcmp(queueName, "suspended-blocked") ==0){ currPtr = SusBlockQueue;

	if(currPtr->head == NULL)
	{
		printf("List is empty.\n");
	}
	else
	{
		next = currPtr->head;
		while(next != NULL)
		{
			printf("%s  ", next -> data);
			next = next->nextPtr;
		}
		printf("\n");
	}
	}
	else{
		printf("Invalid Process State!\n");
		return;
	}
}
